import _ from 'underscore'
import dispatcher from 'lib/dispatcher'
import {Scope} from 'lib/scopeFactory'
import traceDetail from '../apis/traceDetail'
import {parseUri} from '../common/util.jsx';

function flattenTrace(traces,target,lvl){
  _.chain(traces).sortBy('startTime').each(function(i){
    target.push(_.extend({lvl:lvl},i));
    if(i.networks){
      flattenTrace(i.networks,target,lvl+1)
    }
    if(i.traces){
      flattenTrace(i.traces,target,lvl+1)
    }
  })
  return target
}

function parseTrace(list){
  function parseTraceData(data) {
    var obj = {};
    if (!data[0] || !data[0]['type']) {
      console.trace('error parse:', data);
    }
    switch (data[0]['type']) {
      case 'ACTIVITY':
        obj['type'] = data[0]['type'];
        obj['traceVersion'] = data[0]['traceVersion'];
        obj['startTime'] = data[1];
        obj['endTime'] = data[2];
        obj['name'] = data[3];
        _.each(data[4], function(i, n) {
          _.extend(obj, parseTraceData(i));
        });
        break;
      case 'ENVIRONMENT':
        obj['appInfo'] = {
          name: data[1][0],
          version: data[1][1],
          packageName: data[1][2]
        };
        obj['osInfo'] = {
          name: data[2][0],
          version: data[2][1]
        };
        obj['deviceInfo'] = {
          modelName: data[2][2],
          agentName: data[2][3],
          agentVersion: data[2][4],
          serialNum: data[2][5],
          brand: data[2][8],
          ext:data[2][9]
        };
        break;
      case 'TRACE':
        if (!obj['traces']) {
          obj['traces'] = []
        }
        var trace = {
          startTime: data[1],
          type: 'trace',
          endTime: data[2],
          name: data[3],
          method: data[4][1]
        };
        obj['traces'].push(trace)
        _.each(data[5], function(i, n) {
          _.each(parseTraceData(i), function(v, k) {
            if (!trace[k]) {
              trace[k] = v
            } else {
              trace[k] = trace[k].concat(v)
            }
          })
        });
        break;
      case 'NETWORK':
        if (!obj['networks']) {
          obj['networks'] = []
        }
        var network = {
          info: data[0],
          type: 'network',
          startTime: data[1],
          endTime: data[2],
          name: data[3],
          thread: data[4][1]
        }
        if (data[0].uri) {
          let parser = parseUri(data[0].uri);
          network.path = parser.pathname + parser.search + parser.hash;
          network.path = network.path && network.path.length > 56
                         ? network.path.substr(0,53) + '...'
                         : network.path;
        }
        obj['networks'].push(network);
        _.each(data[5], function(i, n) {
          _.each(parseTraceData(i), function(v, k) {
            if (!network[k]) {
              network[k] = v
            } else {
              network[k] = network[k].concat(v)
            }
          })
        });
        break;
      case 'VITALS':
        obj['vitals'] = {
          'memory': parseVitalsData(data[1]['MEMORY']),
          'cpu':parseVitalsData(data[1]['CPU'])
        }
        break;
      case 'RUNNING_APPS':
        obj['otherApp'] = _.chain(data.slice(1)).filter(function(i){
          return !_.isEmpty(i)
        }).map(function(i){
          return {
            pid:i[0],
            name:i[1],
            packages:i[2]&&i[2].split(','),
            mem:parseInt(i[3])
          }
        }).value();
        break;
      case 'ACTIVITY_HISTORY':
        //TODO ACTIVITY_HISTORY
        break;
      default:
        console.log('Unknown Type:', data[0]['type']);
    }
    return obj
  }
  function parseVitalsData(data) {
    if (!data)
      return null;
    return _.map(data, function(i,ind) {
      return {
        count:i[1],
        time:i[0]
      }
    })
  }
  var traceDetail1 = JSON.parse(list['traceDetail']);
  var result = {
    startTime:list['timestamp'],
    endTime:list['timestamp']+list['executeTime']
  };
  _.chain(traceDetail1)
   .filter(item=>_.isArray(item) && item.length)
   .each(function(i, n) {
     _.extend(result, parseTraceData(i));
   });
  if(result.traces&&result.traces.length){
    result.startTime = result.traces[0].startTime;
    result.endTime = result.traces[0].endTime;
  }
  if(result.vitals.cpu){
    var cpuMax = _.chain(result.vitals.cpu).pluck('count').max().value()
    result.vitals.cpu = _.map(result.vitals.cpu,function(i,n,arr){
      return {
        startTime:(n>0)?(arr[n-1]['time'] - result.startTime):0,
        duration:Math.min(i.time,result.endTime) - ((n>0)?Math.max(result.startTime,arr[n-1]['time']):result.startTime),
        count:i.count,
        rate:(i.count/cpuMax)||0
      }
    })
  }
  if(result.vitals.memory){
    var memoryMax = _.chain(result.vitals.memory).pluck('count').max().value()
    result.vitals.memory = _.map(result.vitals.memory,function(i,n,arr){
      return {
        startTime:(n>0)?(arr[n-1]['time'] - result.startTime):0,
        duration:Math.min(i.time,result.endTime) - ((n>0)?Math.max(result.startTime,arr[n-1]['time']):result.startTime),
        count:i.count,
        rate:(i.count/memoryMax)||0
      }
    })
  }
  result.traces = flattenTrace(result.traces,[],0)
  return _.extend({},list,{
    traceDetail:result
  });
}

export default class TraceScope extends Scope {
  constructor(props){
    super();
    this.traceId = props.routeParams.traceId
    this.timestamp = props.routeParams.timestamp;
    this.$state = {
      trace:null
    }
    this.traceApi = traceDetail({
      id:this.traceId,
      timestamp:this.timestamp,
      urlName:'activitytracedetail'
    })
  }
  fetch(){
    var _this = this
    this.traceApi.fetch().then(function(data,params){
      _this.$state.trace = parseTrace(data)
      // console.log(_this.$state.trace)
      _this.emit()
    })
  }
  $unload(){
  }
  $load(){
    var _this = this
    this.fetch();
  }
}
